#include <QVector>
#include <vector>
#include <QPen>
#include <QPainter>
#include <QDebug>
#include <QMessageBox>

#include "roadmapitem.h"
#include "lane.h"
#include "roaddata.h"
#include "../commonfun/commonfun.h"

#define DASHSOLID 20
#define DASHBROKEN 20
#define DASHOFFSET 30
#define LANE_LINE_WIDTHF 0.1

using namespace std;


RoadMapItem::RoadMapItem()
{
    setHandlesChildEvents(false);
}

RoadMapItem::RoadMapItem(const char* path)
{
//    m_pRwXml = new RwXml(path);
//    if(!m_pRwXml->getDoc()){
//        qDebug()<<"加载"<<path<<"失败\n";
//        return;
//    }

//    // 解析xml，获取地图所需标签数据
//    int result = getXmlParseData(m_qvecAllRoad);
//    if (result != 1)
//    {
//        return;
//    }

//    // 计算所有车道线点坐标
//    result = getRoadSurfaceContourPoint(m_qvecAllPoint, m_qvecAllRoad);
//    if (result != 1)
//        return;

//    getRoadInformation();
}

RwXml* RoadMapItem::getDom()
{
    return m_pRwXml;
}

int RoadMapItem::getXmlParseData(QVector<Road>& AllRoad)
{
    // 获取所有道路节点
    vector<TiXmlNode*> vecRoadNode = m_pRwXml->getNodeVec(ROAD);
    if (vecRoadNode.empty())
    {
        qDebug() << "该xml文件中不包含road节点";
        return -1;
    }

    // 遍历解析每条道路
    for (TiXmlNode *pEachRoad : vecRoadNode)
    {
        Road road;
        road.id = CommonFun::judgeTiXmlNodeSuccess(pEachRoad, ID_STR) ? stoll(pEachRoad->ToElement()->Attribute(ID_STR)) : 0;
        road.junction = CommonFun::judgeTiXmlNodeSuccess(pEachRoad, JUNCTION_STR) ? stoll(pEachRoad->ToElement()->Attribute(JUNCTION_STR)) : 0;
        road.length = CommonFun::judgeTiXmlNodeSuccess(pEachRoad, LENGTH_STR) ? stod(pEachRoad->ToElement()->Attribute(LENGTH_STR)) : 0;

        // 获取geometry节点
        TiXmlNode *pPlanViewNode = m_pRwXml->selectSingleNode(PLANVIEW_STR, pEachRoad);
        vector<TiXmlNode*> vecGeometryNode = m_pRwXml->getNodeVec(GEOMETRY_STR, pPlanViewNode);
        // 获取elevation节点
        TiXmlNode *pElevationProfileNode = m_pRwXml->selectSingleNode(ELEVATIONPROFILE_STR, pEachRoad);
        vector<TiXmlNode*> vecElevationNode = m_pRwXml->getNodeVec(ELEVATION_STR, pElevationProfileNode);
        // 获取laneOffset和laneSection节点
        TiXmlNode *pLanesNode = m_pRwXml->selectSingleNode(LANES_STR, pEachRoad);
        vector<TiXmlNode*> vecLaneOffsetNode = m_pRwXml->getNodeVec(LANEOFFSET_STR, pLanesNode);
        vector<TiXmlNode*> vecLaneSectionNode = m_pRwXml->getNodeVec(LANESECTION_STR, pLanesNode);

        // 不同geometry段的道路走势不同，划分数目和elevation段保持一致
        // 不同laneSection的车道数目不一样，划分数目和laneOffset保持一致
        // 判断几何段数目是否正确
        if (road.junction == -1 && vecGeometryNode.size() != vecElevationNode.size())
        {
            qDebug() << "该xml文件中存在geometry和elevation数目不一致的道路";
            return -1;
        }

        // 遍历参考线几何段
        for (TiXmlNode *pEachGeometry : vecGeometryNode)
        {
            Geometry geometry;
            geometry.hdg           = CommonFun::judgeTiXmlNodeSuccess(pEachGeometry, HDG_STR) ? stod(pEachGeometry->ToElement()->Attribute(HDG_STR)) : 0;
            geometry.length        = CommonFun::judgeTiXmlNodeSuccess(pEachGeometry, LENGTH_STR) ? stod(pEachGeometry->ToElement()->Attribute(LENGTH_STR)) : 0;
            geometry.s             = CommonFun::judgeTiXmlNodeSuccess(pEachGeometry, S_COORDINATE) ? stod(pEachGeometry->ToElement()->Attribute(S_COORDINATE)) : 0;
            geometry.x             = CommonFun::judgeTiXmlNodeSuccess(pEachGeometry, X_COORDINATE) ? stod(pEachGeometry->ToElement()->Attribute(X_COORDINATE)) : 0;
            geometry.y             = CommonFun::judgeTiXmlNodeSuccess(pEachGeometry, Y_COORDINATE) ? stod(pEachGeometry->ToElement()->Attribute(Y_COORDINATE)) : 0;
            geometry.pGeometryType = pEachGeometry->FirstChild()->Value();
            if (geometry.pGeometryType == "spiral")
            {
                geometry.extend.a = stod(pEachGeometry->FirstChildElement()->Attribute(CURSTART_STR));
                geometry.extend.b = stod(pEachGeometry->FirstChildElement()->Attribute(CUREND_STR));
            }
            else if (geometry.pGeometryType == "arc")
            {
                geometry.extend.a = stod(pEachGeometry->FirstChildElement()->Attribute(CURVATURE_STR));
            }
            else if (geometry.pGeometryType == "poly3")
            {
                geometry.extend.a = stod(pEachGeometry->FirstChildElement()->Attribute(WIDTH_PARAMETER_A));
                geometry.extend.b = stod(pEachGeometry->FirstChildElement()->Attribute(WIDTH_PARAMETER_B));
                geometry.extend.c = stod(pEachGeometry->FirstChildElement()->Attribute(WIDTH_PARAMETER_C));
                geometry.extend.d = stod(pEachGeometry->FirstChildElement()->Attribute(WIDTH_PARAMETER_D));
            }
            road.vecGeometry.push_back(geometry);
        }

        // 遍历高程
        for (TiXmlNode *pEachElevation : vecElevationNode)
        {
            Elevation elevation;
            elevation.s = CommonFun::judgeTiXmlNodeSuccess(pEachElevation, S_COORDINATE) ? stod(pEachElevation->ToElement()->Attribute(S_COORDINATE)) : 0;
            elevation.coefficients.a = CommonFun::judgeTiXmlNodeSuccess(pEachElevation, WIDTH_PARAMETER_A) ? stod(pEachElevation->ToElement()->Attribute(WIDTH_PARAMETER_A)) : 0;
            elevation.coefficients.b = CommonFun::judgeTiXmlNodeSuccess(pEachElevation, WIDTH_PARAMETER_B) ? stod(pEachElevation->ToElement()->Attribute(WIDTH_PARAMETER_B)) : 0;
            elevation.coefficients.c = CommonFun::judgeTiXmlNodeSuccess(pEachElevation, WIDTH_PARAMETER_C) ? stod(pEachElevation->ToElement()->Attribute(WIDTH_PARAMETER_C)) : 0;
            elevation.coefficients.d = CommonFun::judgeTiXmlNodeSuccess(pEachElevation, WIDTH_PARAMETER_D) ? stod(pEachElevation->ToElement()->Attribute(WIDTH_PARAMETER_D)) : 0;
            road.vecElevation.push_back(elevation);
        }

        // 判断道路段数目是否正确
        if (road.junction == -1 && vecLaneOffsetNode.size() != vecLaneSectionNode.size())
        {
            qDebug() << "该xml文件中存在laneOffset和laneSection数目不一致的道路";
            return -1;
        }

        for (TiXmlNode *pEachLaneOffset : vecLaneOffsetNode)
        {
            LaneOffset laneOffset;
            laneOffset.a = CommonFun::judgeTiXmlNodeSuccess(pEachLaneOffset, WIDTH_PARAMETER_A) ? stod(pEachLaneOffset->ToElement()->Attribute(WIDTH_PARAMETER_A)) : 0;
            laneOffset.b = CommonFun::judgeTiXmlNodeSuccess(pEachLaneOffset, WIDTH_PARAMETER_B) ? stod(pEachLaneOffset->ToElement()->Attribute(WIDTH_PARAMETER_B)) : 0;
            laneOffset.c = CommonFun::judgeTiXmlNodeSuccess(pEachLaneOffset, WIDTH_PARAMETER_C) ? stod(pEachLaneOffset->ToElement()->Attribute(WIDTH_PARAMETER_C)) : 0;
            laneOffset.d = CommonFun::judgeTiXmlNodeSuccess(pEachLaneOffset, WIDTH_PARAMETER_D) ? stod(pEachLaneOffset->ToElement()->Attribute(WIDTH_PARAMETER_D)) : 0;
            road.vecLaneOffset.push_back(laneOffset);
        }

        // 遍历道路段，不同道路段的宽度和车道标识不同
        for (TiXmlNode *pEachLaneSection : vecLaneSectionNode)
        {
            LaneSection laneSection;
            laneSection.s = CommonFun::judgeTiXmlNodeSuccess(pEachLaneSection, S_COORDINATE) ? stod(pEachLaneSection->ToElement()->Attribute(S_COORDINATE)) : 0;  // 车道段起始距离
            // 获取每个车道段的所有车道
            vector<TiXmlNode*> vecLaneNode = m_pRwXml->getNodeVec(LANE_STR, pEachLaneSection);
            // 遍历每个车道
            for (TiXmlNode *pEachlane : vecLaneNode)
            {
                Lane lane;
                lane.iId       = CommonFun::judgeTiXmlNodeSuccess(pEachlane, ID_STR) ? stoi(pEachlane->ToElement()->Attribute(ID_STR)) : 0;    // 车道ID
                lane.pLaneType = CommonFun::judgeTiXmlNodeSuccess(pEachlane, LANE_ITEM_TYPE) ? pEachlane->ToElement()->Attribute(LANE_ITEM_TYPE) : "none";  // 车道类型
                if (lane.iId != 0) {
                    TiXmlNode *pWidthNode = m_pRwXml->selectSingleNode(WIDTH_STR, pEachlane);   // 宽度节点
                    if (!pWidthNode)
                    {
                        qDebug() << "道路" << road.id << "车道" << lane.iId << ": "<< WIDTH_STR <<" 节点不存在";
                    }
                    else
                    {
                        lane.structWidth.a = CommonFun::judgeTiXmlNodeSuccess(pWidthNode, WIDTH_PARAMETER_A) ? stod(pWidthNode->ToElement()->Attribute(WIDTH_PARAMETER_A)) : 0;
                        lane.structWidth.b = CommonFun::judgeTiXmlNodeSuccess(pWidthNode, WIDTH_PARAMETER_B) ? stod(pWidthNode->ToElement()->Attribute(WIDTH_PARAMETER_B)) : 0;
                        lane.structWidth.c = CommonFun::judgeTiXmlNodeSuccess(pWidthNode, WIDTH_PARAMETER_C) ? stod(pWidthNode->ToElement()->Attribute(WIDTH_PARAMETER_C)) : 0;
                        lane.structWidth.d = CommonFun::judgeTiXmlNodeSuccess(pWidthNode, WIDTH_PARAMETER_D) ? stod(pWidthNode->ToElement()->Attribute(WIDTH_PARAMETER_D)) : 0;
                    }
                }

                TiXmlNode *pRoadMarkNode = m_pRwXml->selectSingleNode(ROADMARK_STR, pEachlane);  // 道路标记线
                if (!pRoadMarkNode)
                {
                    qDebug() << "道路" << road.id << "车道" << lane.iId << ": "<< ROADMARK_STR <<" 节点不存在";
                    return -1;
                }
                lane.pRoadMarkColor = CommonFun::judgeTiXmlNodeSuccess(pRoadMarkNode, COLOR_STR) ? pRoadMarkNode->ToElement()->Attribute(COLOR_STR) : "standard";
                lane.pRoadMarkType  = CommonFun::judgeTiXmlNodeSuccess(pRoadMarkNode, LANE_ITEM_TYPE) ? pRoadMarkNode->ToElement()->Attribute(LANE_ITEM_TYPE) : "none";

                laneSection.vecLaneInformation.push_back(lane);
            }

            road.vecLaneSection.push_back(laneSection);
        }

        AllRoad.push_back(road);
    }

    return 1;
}

void RoadMapItem::getGeometryLaneData(Geometry &geometry, LaneOffset &laneOffset, Lane &lane, double dSOffset, double dstartds, double dendds, QVector<QVector<QPointF>> &lanesPoint)
{
    if (geometry.pGeometryType == LINE_STR)
    {
       __RODADATA->getGeometryLineData(dSOffset, dstartds, dendds, 1, geometry, laneOffset, lane, lanesPoint);
    }
    else if (geometry.pGeometryType == SPIRAL_STR)
    {

    }
    else if (geometry.pGeometryType == ARC_STR)
    {
        __RODADATA->getGeometryArcData(dSOffset, dstartds, dendds, 1, geometry, laneOffset, lane, lanesPoint);
    }
    else if (geometry.pGeometryType == POLY3_STR)
    {
        __RODADATA->getGeometryPoly3Data(dSOffset, dstartds, dendds, 1, geometry, lane, lanesPoint);
    }
}

void RoadMapItem::setLaneLine(const QVector<Painting> &qvecLaneLine)
{
    m_qvecLaneLine = qvecLaneLine;
}

void RoadMapItem::appendFilling(const Painting filling)
{
    m_qvecFiling.append(filling);
}

void RoadMapItem::appendLaneLine(const Painting laneLine)
{
    m_qvecLaneLine.append(laneLine);
}

void RoadMapItem::setFilling(const QVector<Painting> &qvecFilling)
{
    m_qvecFiling = qvecFilling;
}

void RoadMapItem::setRoadMapLane(const RoadMapLane &roadMapLane)
{
    m_roadMapLane = roadMapLane;
}

void RoadMapItem::setRoadMapPaint(const RoadMapPaint &roadMapPaint)
{
    m_roadMapPaint = roadMapPaint;
}

QVector<SController> RoadMapItem::getController() const
{
    return m_qvecController;
}

void RoadMapItem::setController(const QVector<SController> &qvecController)
{
    m_qvecController = qvecController;
}

QVector<Junction> RoadMapItem::getJunction() const
{
    return m_qvecJunction;
}

void RoadMapItem::setJunction(const QVector<Junction> &qvecJunction)
{
    m_qvecJunction = qvecJunction;
}

void RoadMapItem::onMap(RoadItem *pRoadItem, LaneItem *pLaneItem, const QPointF &pointf)
{
    qDebug() << "LaneID: " << pLaneItem->getId() <<"\n";
    qDebug() << "LaneType: " << pLaneItem->getLaneType() <<"\n";
    qDebug() << "RoadID: " << pRoadItem->getId() <<"\n";
    emit sigSendMapInfo(pRoadItem, pLaneItem, pointf);
}

QVector<QVector<QPointF>> RoadMapItem::getGeometryData(LaneOffset &laneOffset, LaneSection &laneSection, Geometry &geometry, double dstartds, double dendds)
{
    int index = laneSection.vecLaneInformation[0].iId;

    // 地理几何元素s 减 车道段s，得到相对车道段起始点的距离
    // 如果几何元素距离大于车道段距离，以几何元素的相对值为起始
    // 如果几何元素距离小于车道段距离，以车道段的相对值为起始
    double sOffset = 0.0;
    if (geometry.s > laneSection.s)
    {
        sOffset = geometry.s - laneSection.s;
    }

    // 左侧车道包括0车道
    QVector<QVector<QPointF>> leftLanesPoint;
    for (int i = index; i >= 0; --i)
    {
        Lane eachLane = laneSection.vecLaneInformation[i];
        getGeometryLaneData(geometry, laneOffset, eachLane, sOffset, dstartds, dendds, leftLanesPoint);
    }

    // 右侧车道包括0车道
    QVector<QVector<QPointF>> rightLanesPoint;
    rightLanesPoint.push_back(leftLanesPoint[0]);
    for (int i = index+1; i < laneSection.vecLaneInformation.size(); ++i)
    {
        Lane eachLane = laneSection.vecLaneInformation[i];
        getGeometryLaneData(geometry, laneOffset, eachLane, sOffset, dstartds, dendds, rightLanesPoint);
    }

    // 调整顺序和车道段车道顺序一致
    QVector<QVector<QPointF>> allLanesPoint;
    for (int i = index; i >= 0; --i)
    {
        allLanesPoint.push_back(leftLanesPoint[i]);
    }
    // 从下标1开始过滤掉多余的0车道
    for (int j = 1; j < rightLanesPoint.size(); ++j)
    {
        allLanesPoint.push_back(rightLanesPoint[j]);
    }

    return allLanesPoint;
}

QVector<QVector<QPointF>> RoadMapItem::getLaneSectionPoint(LaneOffset &laneOffset, LaneSection &laneSection, QVector<Geometry> &vecGeometry, double dlaneStart, double dlaneEnd)
{
    int i,j;
    Geometry eachGeometry;
    double geometry_start_s;

    for (i = 0; i < vecGeometry.size(); ++i)
    {
        eachGeometry = vecGeometry[i];
        geometry_start_s = eachGeometry.s;
        if (geometry_start_s > dlaneStart)
            break;
    }

    for (j = 0; j < vecGeometry.size(); ++j)
    {
        eachGeometry = vecGeometry[j];
        geometry_start_s = eachGeometry.s;
        if (geometry_start_s >= dlaneEnd)
            break;
    }
    i -= 1;
    j -= 1;

    QVector<QVector<QVector<QPointF>>> allRelativelyLaneSection;
    double drelativelyStart, drelativelyEnd;
    for (int k = i; k <= j; ++k)
    {
        QVector<QVector<QPointF>> eachRelativelyLaneSection;
        eachGeometry = vecGeometry[k];
        if (0 == (j - i))
        {
            drelativelyStart = dlaneStart - eachGeometry.s;
            drelativelyEnd = dlaneEnd - eachGeometry.s;
        }
        else if (1 == (j - i))
        {
            if (k == i)
            {
                drelativelyStart = dlaneStart - eachGeometry.s;
                drelativelyEnd = eachGeometry.length;
            }
            else
            {
                drelativelyStart = 0;
                drelativelyEnd = dlaneEnd - eachGeometry.s;
            }
        }
        else if (1 < (j - i))
        {
            if (k == i)
            {
                drelativelyStart = dlaneStart - eachGeometry.s;
                drelativelyEnd = eachGeometry.length;
            }
            else if (k == j)
            {
                drelativelyStart = 0;
                drelativelyEnd = dlaneEnd - eachGeometry.s;
            }
            else
            {
                drelativelyStart = 0;
                drelativelyEnd = eachGeometry.length;
            }
        }
        else
        {
            assert("other case");
        }

        // 车道段对应的几何元素
        eachRelativelyLaneSection = getGeometryData(laneOffset, laneSection, eachGeometry, drelativelyStart, drelativelyEnd);
        allRelativelyLaneSection.push_back(eachRelativelyLaneSection);
    }

    // 将相对车道段合并
    QVector<QVector<QPointF>> eachLaneSection;
    mergeAllRelativelyLaneSection(eachLaneSection, allRelativelyLaneSection);

    return eachLaneSection;
}

void RoadMapItem::mergeAllRelativelyLaneSection(QVector<QVector<QPointF>> &vecEachLaneSection, const QVector<QVector<QVector<QPointF>>> vecAllRelativelyLaneSection)
{
    for(auto eachRelativelyLaneSection : vecAllRelativelyLaneSection)
    {
        for(int i = 0; i < eachRelativelyLaneSection.size(); ++i)
        {
            if (vecEachLaneSection.size() < eachRelativelyLaneSection.size())
            {
                vecEachLaneSection.push_back(eachRelativelyLaneSection[i]);
            }
            else
            {
                vecEachLaneSection[i] += eachRelativelyLaneSection[i];
            }
        }

    }
}

// 获取道路表面轮廓点
int RoadMapItem::getRoadSurfaceContourPoint(QVector<QVector<QVector<QVector<QPointF>>>>& qAllPoint ,const QVector<Road> qAllRoad)
{
    for (Road eachRoad : qAllRoad)
    {
        double droadLength = eachRoad.length;
        QVector<QVector<QVector<QPointF>>> vecRoad;
        for (int i = 0; i < eachRoad.vecLaneSection.size(); ++i)
        {
//            int id = eachRoad.id;
//            if (id != 14007)
//                continue;
            QVector<QVector<QPointF>> vecLaneSection;
            LaneSection eachLaneSection = eachRoad.vecLaneSection[i];
            double dlaneStart = eachLaneSection.s;
            double dlaneEnd = 0;
            if (i+1 == eachRoad.vecLaneSection.size())
            {
                dlaneEnd = droadLength;
            }
            else
            {
                dlaneEnd = eachRoad.vecLaneSection[i+1].s;

            }
            // 车道段
            LaneOffset eachLaneOffset = eachRoad.vecLaneOffset[i];
            vecLaneSection = getLaneSectionPoint(eachLaneOffset, eachLaneSection, eachRoad.vecGeometry, dlaneStart, dlaneEnd);
            vecRoad.push_back(vecLaneSection);
        }
        qAllPoint.push_back(vecRoad);
    }

    return 1;
}

void RoadMapItem::getRoadInformation()
{
//    for (Road eachRoad : m_qvecAllRoad)
//    {
//        QVector< QVector<Lane> > vecLaneSectionInformation;
//        for (int i = 0; i < eachRoad.vecLaneSection.size(); ++i)
//        {
//            LaneSection eachLaneSection = eachRoad.vecLaneSection[i];
//            vecLaneSectionInformation.push_back(eachLaneSection.vecLaneInformation);
//        }

//        //m_vecLaneInformation.push_back(vecLaneSectionInformation);
//    }
}

void RoadMapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem*, QWidget*)
{
    painter->setRenderHint(QPainter::Antialiasing);
    QPen pen(Qt::NoPen);
    painter->setPen(pen);

    //填充
    for(auto filling: m_qvecFiling)
    {
        painter->setBrush(__RODADATA->getColor(filling.qstrColor));
        painter->drawPolygon(filling.polygonF);
    }

    //车道线
    pen.setWidthF(LANE_LINE_WIDTHF);
    for(auto laneLine: m_qvecLaneLine)
    {
        pen.setColor(__RODADATA->getColor(laneLine.qstrColor));
        pen.setStyle(__RODADATA->getPenStyle(laneLine.qstrStyle));

        if(XML_BROKEN == laneLine.qstrStyle)
        {
            pen.setDashPattern(QVector<qreal>() << DASHSOLID << DASHBROKEN);
            pen.setDashOffset(DASHOFFSET);
        }

        pen.setCapStyle(Qt::FlatCap);
        painter->setPen(pen);
        painter->drawPolyline(laneLine.polygonF);
    }
}
